#pragma once

#include <iostream>
#include <vector>
#include <queue>
#include <unistd.h>
#include "LockGuard.hpp"
#include "Thread.hpp"
#include "Functions.hpp"
#include "../lib/Log.hpp"
using namespace std;

#define Default_Thread_Num 3

// 单例模式-懒汉
// 构造私有化，拷贝赋值删除，自动析构
// 考虑多线程开始的时候实例化线程池的线程安全问题，加锁
// 静态的成员线程池指针，静态的锁（后面解释为什么是静态），内部类实现自动析构

// todo两个队列的多线程调用线程池场景

template <class T>
class Thread_Pool
{
private:
    Thread_Pool(size_t num = Default_Thread_Num) : _num(num), _cond(_lock.ret_mutex())
    {
        for (int i = 1; i <= num; ++i)
        {
            // routine函数需要拿到任务队列，传this指针
            _threads.push_back(new Thread(i, routine, (void *)this));
        }
    }
    Thread_Pool(const Thread_Pool<T> &) = delete;
    Thread_Pool<T> &operator=(const Thread_Pool<T> &) = delete;
    // void operator delete(void*);

public:
    static Thread_Pool<T> *Creat_Threadpool(int num = Default_Thread_Num)
    {
        // 保证第一次实例化的时候线程安全
        if (_tp_ptr == nullptr)
        {
            // LockGuard_static(&_lock_static);
            // pthread_mutex_lock(&_lock_static);
            LockGuard_static lock(&_lock_static);
            if (_tp_ptr == nullptr)
            {
                Messagelog(NORMAL, "%s\n", "线程池创建成功");
                _tp_ptr = new Thread_Pool<T>(num);
            }
            // pthread_mutex_unlock(&_lock_static);
        }

        return _tp_ptr;
    }

    void run()
    {
        if (!_run)
        {
            for (auto &t : _threads)
            {
                t->run();
                Messagelog(NORMAL, "%s %s", t->name().c_str(), "启动成功");
            }
            _run = true;
        }
    }

private:
    // 列程函数负责从任务队列获取任务去执行
    static void *routine(void *args)
    {
        // 这里的args是从Thread函数的creat里获取的，Thread_Data
        Thread_Data *td = (Thread_Data *)args;
        Thread_Pool<T> *tp = (Thread_Pool<T> *)td->args;

        while (true)
        {

            // 拿任务
            T task;
            {
                // LockGuard lock(&(tp->_lock));
                // LockGuard (tp->ret_plock()); // 犯得最sb的错误
                LockGuard lock(tp->ret_plock());
                while (tp->Tasks_Is_Empty())
                {
                    // Messagelog(DEBUG, "%s %s %d", td->name.c_str(), "条件等待，阻塞中！", tp->ret_tasks_size());
                    // tp->_cond.wait();
                    tp->cond_wait();
                    // Messagelog(DEBUG, "%s %s %d", td->name.c_str(), "我被唤醒了", tp->ret_tasks_size());
                }
                task = tp->gettask();
                // Messagelog(NORMAL, "%s 处理任务", td->name.c_str());
            }
            // 处理任务
            task();
        }
    }

public:
    // 生产者放任务
    void push_task(const T &task)
    {
        LockGuard lock(&_lock);
        _tasks.push(task);

        _cond.signal();
    }

    ~Thread_Pool()
    {
        for (auto &t : _threads)
        {
            t->join();
        }
        pthread_mutex_destroy(&_lock_static);
    }

private:
    bool Tasks_Is_Empty()
    {
        return _tasks.empty();
    }

    Lock *ret_plock()
    {
        return &_lock;
    }

    int ret_tasks_size()
    {
        return _tasks.size();
    }

    void cond_wait()
    {
        _cond.wait();
    }

    T gettask()
    {
        T task = _tasks.front();
        _tasks.pop();
        return task;
    }

private:
    std::vector<Thread *> _threads;
    size_t _num;
    std::queue<T> _tasks;
    Lock _lock;
    Cond _cond;
    bool _run = false;

    static Thread_Pool<T> *_tp_ptr;
    // static Lock _creat_lock;
    // static Lock_static _lock_static;
    static pthread_mutex_t _lock_static;
};

// static定义的是静态的，必须要用静态的初始化方式
// template<class T>
// Lock Thread_Pool<T>::_creat_lock;

template <class T>
Thread_Pool<T> *Thread_Pool<T>::_tp_ptr = nullptr;

// template<class T>
// Lock_static Thread_Pool<T>::_lock_static;
template <class T>
pthread_mutex_t Thread_Pool<T>::_lock_static = PTHREAD_MUTEX_INITIALIZER;
